{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "fa9d519a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from itertools import accumulate\n",
    "from math import sqrt\n",
    "np.set_printoptions(precision=5, suppress=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5f5d397c",
   "metadata": {},
   "outputs": [],
   "source": [
    "lista=[[1,2],[4,4],[-1,3],[16,22],[-42,0],[22,-21]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "35bd1cf7",
   "metadata": {},
   "outputs": [],
   "source": [
    "homo_lista=[[7,4,1],[6,4,2],[5,2,0.5],[0,0,10],[-5,-5,1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f94edc54",
   "metadata": {},
   "outputs": [],
   "source": [
    "trapez1 = [[- 3, - 1, 1], [3, - 1, 1], [1, 1, 1], [- 1, 1, 1], [1,2,3], [-8,-2,1]] \n",
    "pravougaonik1 = [[- 2, - 1, 1], [2, - 1, 1], [2, 1, 1], [- 2, 1, 1], [2,1,5], [-16,-5,5]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "752f8b96",
   "metadata": {},
   "outputs": [],
   "source": [
    "orig=[[-3,-1,1],[3,-1,1],[1,1,1],[-1,1,1]]\n",
    "slike=[[-2,-1,1],[2,-1,1],[2,1,1],[-2,1,1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f31e1985",
   "metadata": {},
   "outputs": [],
   "source": [
    "def afinizuj(niz):\n",
    "    return list(map(lambda x : [x[0]/x[2],x[1]/x[2]], niz))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "60d26426",
   "metadata": {},
   "outputs": [],
   "source": [
    "def homo(niz):\n",
    "    return list(map(lambda x : [x[0],x[1],1], niz))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e7621037",
   "metadata": {},
   "source": [
    "Normalizacija tacaka za odredjivanje matrice projektivnog preslikavanja."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "466c5ad9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def normMatrix(lista):\n",
    "    lista1=np.array(afinizuj(lista))\n",
    "    teziste1=(list(accumulate(lista1))[-1])/(len(lista))\n",
    "    lista2=np.array(lista1-teziste1)\n",
    "    inteziteti=np.array(list(map(lambda x: [sqrt(x[0]*x[0]+x[1]*x[1])],lista2)))\n",
    "    d=(list(accumulate(inteziteti))[-1])/(len(lista))\n",
    "    translacija=np.array([[1,0,0],[0,1,0],np.append(-teziste1,1)])\n",
    "    translacija=translacija.transpose()\n",
    "    homotetija=np.array([[sqrt(2)/float(d),0,0],[0,sqrt(2)/float(d),0],[0,0,1]])\n",
    "    transform=np.matmul(homotetija,translacija)\n",
    "    nova_lista=[]\n",
    "    for x in np.array(lista):\n",
    "        x=x.reshape(3,1)\n",
    "        x=np.matmul(transform,x)\n",
    "        nova_lista.append([x[0,0],x[1,0],x[2,0]])\n",
    "    return nova_lista,transform"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ea6709e",
   "metadata": {},
   "source": [
    "Normiranje matrice"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0ff1ada1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def norm_matrix(matrica):\n",
    "    return matrica/matrica[2,2]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9603019",
   "metadata": {},
   "source": [
    "DLT i DLT sa normalizacijom"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "7b5641e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def DLT(originali,slike):\n",
    "    matrica=[]\n",
    "    for x,y in zip(originali,slike):\n",
    "        prvi=[0,0,0,-y[2]*x[0],-y[2]*x[1],-y[2]*x[2],y[1]*x[0],y[1]*x[1],y[1]*x[2]]\n",
    "        drugi=[y[2]*x[0],y[2]*x[1],y[2]*x[2],0,0,0,-y[0]*x[0],-y[0]*x[1],-y[0]*x[2]]\n",
    "        matrica.append(prvi)\n",
    "        matrica.append(drugi)\n",
    "    matrica=np.array(matrica)\n",
    "    U,D,VT=np.linalg.svd(matrica)\n",
    "    p=VT[-1]\n",
    "    return norm_matrix(p.reshape(3,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4eada370",
   "metadata": {},
   "outputs": [],
   "source": [
    "def DLTwithNormalization(originali,slike):\n",
    "    originali,T=normMatrix(originali)\n",
    "    slike,T1=normMatrix(slike)\n",
    "    p=DLT(originali,slike)\n",
    "    p=np.linalg.inv(T1)@p@T\n",
    "    return norm_matrix(p)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bdb90da",
   "metadata": {},
   "source": [
    "Implementacija naivnog algoritma za odredjivanje matrice projektivnog preslikavanja."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "5a737608",
   "metadata": {},
   "outputs": [],
   "source": [
    "def opsti_polozaj(lista):\n",
    "    x1, x2, x3, x4 = lista[0], lista[1], lista[2], lista[3]\n",
    "    if min(np.abs([np.linalg.det([x1, x2, x3]),\n",
    "                      np.linalg.det([x2, x3, x4]),\n",
    "                      np.linalg.det([x3, x4, x1]),\n",
    "                      np.linalg.det([x4, x1, x2])])) == 0:\n",
    "        return False\n",
    "    return True\n",
    "\n",
    "def naivni(originali,slike):\n",
    "    if not opsti_polozaj(originali):\n",
    "        return \"Losi originali!\"\n",
    "    if not opsti_polozaj(slike):\n",
    "        return \"Lose slike!\"\n",
    "    b=originali.pop(3)\n",
    "    b1=slike.pop(3)\n",
    "    x=np.linalg.solve(np.asmatrix(originali).transpose(),b)\n",
    "    x1=np.linalg.solve(np.asmatrix(slike).transpose(),b1)\n",
    "    x=np.array(list(map(lambda z:[z],x)))\n",
    "    x1=np.array(list(map(lambda z:[z],x1)))\n",
    "    p1=np.column_stack(originali*x)\n",
    "    p2=np.column_stack(slike*x1)\n",
    "    p=p2@(np.linalg.inv(p1))\n",
    "    for i in range(0,3):\n",
    "        p[i,]=list(map(lambda x: 0 if abs(x)<1e-10 else x,p[i,]))\n",
    "    return norm_matrix(p)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d8963b4",
   "metadata": {},
   "source": [
    "Deo sa interfejsom koji implementira neku od funkcija za odredjivanje matrice projektivnog preslikavanja i transformise tacke zadate klikom na interfejsu, radi otklanjanja projektivne distorzije."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f7126c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2 as cv\n",
    "import numpy as np\n",
    "import math\n",
    "\n",
    "putanja = './karta.jpg'\n",
    "slika = cv.imread(putanja)\n",
    "\n",
    "tacke = []\n",
    "brojac = 0\n",
    "def click_event(event, x, y, flags, params): \n",
    "    global brojac,tacke\n",
    "    font = cv.FONT_HERSHEY_SIMPLEX \n",
    "\n",
    "    if event == cv.EVENT_LBUTTONDOWN: \n",
    "        cv.putText(slika, str(x) + ',' +\n",
    "                    str(y), (x,y), font, \n",
    "                    1, (255, 0, 0), 2) \n",
    "        cv.imshow(\"karta\", slika)\n",
    "        \n",
    "        tacke.append([x, y, 1])\n",
    "        brojac += 1\n",
    "        \n",
    "        if brojac == 4:\n",
    "            odnos=1.667\n",
    "            visina=math.sqrt((tacke[2][0]-tacke[1][0])*(tacke[2][0]-tacke[1][0])+(tacke[2][1]-tacke[1][1])*(tacke[2][1]-tacke[1][1]))\n",
    "            sirina=odnos*visina;\n",
    "            tacke2 = np.float32([[tacke[0][0],tacke[0][1],1], [tacke[0][0]+sirina, tacke[0][1],1], [tacke[0][0]+sirina, tacke[0][1]+visina,1], [tacke[0][0], tacke[0][1]+visina,1]])\n",
    "            #P=DLTwithNormalization(list(tacke),list(tacke2))\n",
    "            P=naivni(list(tacke),list(tacke2))\n",
    "            offset=200\n",
    "            trans=np.zeros((int(sirina+offset),int(visina+offset)),dtype=np.uint8)\n",
    "            out=cv.warpPerspective(slika,P,(slika.shape[1],slika.shape[0]),flags=cv.INTER_LINEAR)\n",
    "            cv.imshow(\"izlaz\",out)\n",
    "            \n",
    "\n",
    "cv.imshow(\"karta\", slika)\n",
    "\n",
    "cv.setMouseCallback(\"karta\", click_event)\n",
    "\n",
    "cv.waitKey(0)\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3bd5583c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be730fea",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
